package com.lagou.ipersistence.executor.resultset;

import com.lagou.ipersistence.mapping.ResultMap;
import com.lagou.ipersistence.session.Configuration;
import com.lagou.ipersistence.type.JdbcType;
import com.lagou.ipersistence.type.TypeHandler;
import com.lagou.ipersistence.type.TypeHandlerRegistry;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * @author Yan Jiahong
 * Created on 2020/11/23
 */
public class ResultSetWrapper {
    private final ResultSet resultSet;
    private final TypeHandlerRegistry typeHandlerRegistry;
    private final List<String> columnNames = new ArrayList<>();
    private final List<JdbcType> jdbcTypes = new ArrayList<>();
    
    private final ResultMap resultMap;
    private List<String> mappedColumns;
    private List<String> unMappedColumns;
    
    public ResultSetWrapper(ResultSet resultSet, Configuration configuration, ResultMap resultMap) throws SQLException {
        this.resultSet = resultSet;
        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
        // 因为目前的版本是MySQL, 只有一个ResultSet, 所以可以直接在开始的时候传入一个ResultMap即可
        this.resultMap = resultMap;
        final ResultSetMetaData metaData = resultSet.getMetaData();
        for (int i = 1; i < metaData.getColumnCount() + 1; i++) {
            columnNames.add(metaData.getColumnName(i));
            jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i)));
        }
    }
    
    public ResultSet getResultSet() {
        return resultSet;
    }
    
    public List<String> getColumnNames() {
        return columnNames;
    }
    
    public JdbcType getJdcType(String columnName) {
        for (int i = 0; i < columnNames.size(); i++) {
            if (columnNames.get(i).equalsIgnoreCase(columnName)) {
                return jdbcTypes.get(i);
            }
        }
        return null;
    }
    
    public List<String> getUnMappedColumns() {
        if (unMappedColumns == null) {
            loadMappedAndUnMappedColumnNames();
        }
        return unMappedColumns;
    }
    
    private void loadMappedAndUnMappedColumnNames() {
        mappedColumns = new ArrayList<>();
        unMappedColumns = new ArrayList<>();
        for (String colName : columnNames) {
            final String upperColName = colName.toUpperCase(Locale.ENGLISH);
            if (resultMap.getMappedColumns().contains(upperColName)) {
                mappedColumns.add(colName);
            } else {
                unMappedColumns.add(colName);
            }
        }
    }
    
    public TypeHandler<?> getTypeHandler(Class<?> propertyType, String columnName) {
        JdbcType jdbcType = getJdcType(columnName);
        return typeHandlerRegistry.getTypeHandler(propertyType, jdbcType);
    }
}
